<?php
/**
 * Enter description here...
 *
 * @package if
 * @subpackage module.db.drivers
 * @since 1.0.1
 */
class IDbMssqlDriver extends IDbDriver {
	protected $startQuote = "[";
	protected $endQuote = "]";
	
	protected $commands = array(
		"begin"    => "BEGIN TRANSACTION",
		"commit"   => "COMMIT",
		"rollback" => "ROLLBACK"
	);	
	
	protected $metaTableSQL = "select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE','dtproperties'))";
	
	function __construct(array $config) {
		parent::__construct($config);
		if (!extension_loaded("mssql")) {
			throw new IDbException("mssql extension not be loaded", 0x100073);
		}
		
		$this->support["offset"] = false;
	}
	
	/**
	 * Enter description here...
	 *
	 * @param unknown_type $name
	 * @return array
	 */
	function describeTable($name) {
	   	$rows = $this->fetchAll($this->nativeExec("SELECT COLUMN_NAME as Field, DATA_TYPE as Type, COL_LENGTH('{$name}', COLUMN_NAME) as Length, IS_NULLABLE As [Null], COLUMN_DEFAULT as [Default], COLUMNPROPERTY(OBJECT_ID('{$name}'), COLUMN_NAME, 'IsIdentity') as [Key], NUMERIC_SCALE as Size FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{$name}'"));
	   	$fields = array();
	   	foreach ($rows as $row) {
	   		$column = $row["Field"];
	   		$fields[$column] = array(
	   			"name" =>$column,
	   			"type" => $row["Type"],
	   			"max_length" => $row["Length"],
	   			"not_null" => $row["Null"],
	   			"default_value" => $row["Default"],
	   			"primary_key" => $row["Key"],
	   		);
	   		$fields[$column]["data_type"] = $this->dataType($fields[$column]);
	   	}
	   	return $fields;
	}
	
	protected function nConnect() {
		$conn = null;
		//连接
		$host = isset($this->config["port"]) ? $this->config["host"] . ":" . $this->config["port"]:$this->config["host"];
		$host = isset($this->config["socket"]) ? $this->config["host"] . ":" . $this->config["socket"]:$this->config["host"];
		if (!$this->config("persist")) {
			$conn = @mssql_connect($host, $this->config["username"], $this->config["password"]);
		}
		else {
			$conn = @mssql_pconnect($host, $this->config["username"], $this->config["password"]);
		}
		if (!$conn) {
			throw new IDbException("Can't connect to MS SQL server on '" . $this->config["host"] . "'", 0x100074);
		}
		
		//数据库
		mssql_select_db($this->config["dbname"], $conn);
		return $conn;
	}
	
	protected function nClose() {
		return $this->connect() ? mssql_close($this->connect()) : true;
	}
	
	function lastInsertId($name = null) {
		$row = $this->fetch($this->nativeExec("SELECT SCOPE_IDENTITY() AS insertID"), IDb::FETCH_NUM);
		return $row[0];
	}
	
	function nLimit($sql, $count, $offset = 0) {
		return $sql = preg_replace("/^SELECT\s/i", "SELECT TOP " . ($count + $offset) . " ", $sql);
	}
	
	protected function nQuote($data) {
		if (is_int($data) || is_float($data)) {
			return $data;
		}
		if(is_null($data)) {
			return "NULL";
		}
		return "'" . mssql_($data, $this->connect()) . "'";
	}
	
	function exec($sql) {
		$this->_log("execute:{$sql}");
		mssql_execute($sql, $this->connect());
		$this->_free();
		return mssql_affected_rows($this->connect());
	}
	
	function nativeExec($sql) {
		$result = mssql_query($sql, $this->connect());
		$this->_free();
		return $result;
	}
	
	/**
	 * Enter description here...
	 *
	 * @param unknown_type $result
	 * @param unknown_type $fetchType
	 * @param unknown_type $arguments
	 * @return unknown
	 * @todo FETCH_OBJ是支持class名
	 */
	function fetch($result, $fetchType = IDb::FETCH_BOTH, $columnIndex = 0) {
		if (!$result) {
			return;
		}
		switch ($fetchType) {
			case IDb::FETCH_BOTH:
				return mssql_fetch_array($result, MSSQL_BOTH);
				break;
			case IDb::FETCH_ASSOC:
				return mssql_fetch_array($result, MSSQL_ASSOC);
			case IDb::FETCH_NUM:
				return mssql_fetch_array($result, MSSQL_NUM);
			case IDb::FETCH_OBJ:
				return mssql_fetch_object($result);
			case IDb::FETCH_COLUMN:
				$row = mssql_fetch_row($result);
				if (!empty($row)) {
					if (array_key_exists($columnIndex, $row)) {
						return $row[$columnIndex];
					}
				}
		}
		return null;
	}
	
	function error() {
		return array();
	}
	
	private function _free($result = null) {
		if (gettype($result) == "resource") {
			mssql_free_result($result);
		}
		$error = $this->error();
		if (!empty($error)) {
			throw new IDbException($error["message"], $error["code"]);
		}
	}
	
	function rowCount($result) {
		return is_resource($result) ? mssql_num_rows($result) : mssql_affected_rows($this->connect());
	}	
	
	function move($result, $offset) {
		return mssql_data_seek($result, $offset);
	}	
}

?>